package com.tsfyun.scm.service.impl.support;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tsfyun.common.base.config.properties.DDRemindProperties;
import com.tsfyun.common.base.enums.MsgContentTypeEnum;
import com.tsfyun.common.base.enums.domain.DomainOprationEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.help.DingTalkNoticeUtil;
import com.tsfyun.common.base.security.LoginVO;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.common.base.validator.ValidatorUtils;
import com.tsfyun.scm.config.ws.WsBiz;
import com.tsfyun.scm.dto.support.TaskNoticeContentDTO;
import com.tsfyun.scm.dto.support.TaskNoticeContentQTO;
import com.tsfyun.scm.dto.support.TaskNoticeDTO;
import com.tsfyun.scm.dto.support.WsMessageDTO;
import com.tsfyun.scm.entity.support.TaskNoticeContent;
import com.tsfyun.scm.entity.support.TaskNoticeFocus;
import com.tsfyun.scm.entity.system.SysMenu;
import com.tsfyun.scm.mapper.support.TaskNoticeContentMapper;
import com.tsfyun.scm.service.support.ITaskNoticeContentService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.service.support.ITaskNoticeFocusService;
import com.tsfyun.scm.service.support.ITaskNoticeService;
import com.tsfyun.scm.service.system.ISysMenuService;
import com.tsfyun.scm.service.user.IPersonService;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.support.TaskNoticeContentVO;
import com.tsfyun.scm.vo.user.SimplePersonInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 任务通知内容 服务实现类
 * </p>
 *

 * @since 2020-04-05
 */
@RefreshScope
@Service
public class TaskNoticeContentServiceImpl extends ServiceImpl<TaskNoticeContent> implements ITaskNoticeContentService {

    @Autowired
    private TaskNoticeContentMapper taskNoticeContentMapper;

    @Autowired
    private ITaskNoticeService taskNoticeService;

    @Autowired
    private ISysMenuService sysMenuService;

    @Autowired
    private IPersonService personService;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    private WsBiz wsBiz;

    @Value("${scm.manage.role.code}")
    private String manageRoleCode;

    @Value("${task.notice.manager.receive:true}")
    private boolean taskNoticeManagerReceive;

    @Autowired
    private ITaskNoticeFocusService taskNoticeFocusService;

    @Resource
    private DDRemindProperties ddRemindProperties;

    @Value("${spring.profiles.active:dev}")
    private String profiles;

    static final List<String> ddRemindOperationCodes = new ArrayList<String>(){{
        add(DomainOprationEnum.ORDER_PRICING.getCode());//审价
        add(DomainOprationEnum.ORDER_PRICE_EXAMINE.getCode());//订单审价
        add(DomainOprationEnum.RISK_APPROVAL_AUDIT.getCode());//风控审批
        add(DomainOprationEnum.PAYMENT_ACCOUNT_AUDIT.getCode());//付汇商务审核
        add(DomainOprationEnum.REFUND_AUDIT.getCode());//退款审核
        add(DomainOprationEnum.CROSS_BORDER_WAYBILL_REVIRE.getCode());//复核跨境运输
        add(DomainOprationEnum.CROSS_BORDER_WAYBILL_BIND.getCode());//复核跨境运输
        add(DomainOprationEnum.ORDER_CONFIRMIMP.getCode());//订单进口确认
    }};

    @Override
    public void add(TaskNoticeContentDTO dto) {
        //基本校验
        ValidatorUtils.validateEntity(dto,null);
        //跨线程里面获取不到
        LoginVO loginVO = SecurityUtil.getCurrent();
        String loginPersonIdAndName = SecurityUtil.getCurrentPersonIdAndName();
        threadPoolTaskExecutor.execute(()->{
            try {
                Map<String, Object> actionParamsMap = dto.getActionParamsMap();
                if (CollUtil.isEmpty(actionParamsMap)) {
                    actionParamsMap = Maps.newHashMap();
                }
                Map<String, Object> queryParamsMap = dto.getQueryParamsMap();
                if (CollUtil.isEmpty(queryParamsMap)) {
                    queryParamsMap = Maps.newHashMap();
                }

                TaskNoticeContent taskNoticeContent = beanMapper.map(dto, TaskNoticeContent.class);
                //如果某类型的单据对应的操作码存在数据，则先删掉再新增
                deleteTaskNotice(dto.getDocumentType(), dto.getDocumentId(), dto.getOperationCode());
                //跳转页面从菜单表中取
                SysMenu sysMenu = sysMenuService.findByOperationCode(dto.getOperationCode());
                List<SimplePersonInfo> personInfos = null;
                if (Objects.nonNull(sysMenu)) {
                    actionParamsMap.put("pmid", sysMenu.getParentId());
                    personInfos = personService.getPersonByMenuId(sysMenu.getId());
                    if (taskNoticeManagerReceive) {
                        //获取管理员组下员工信息
                        List<SimplePersonInfo> managerPersons = personService.getPersonByRoleId(manageRoleCode);
                        personInfos.addAll(managerPersons);
                    }
                }

                taskNoticeContent.setCustomerId(dto.getCustomerId());
                taskNoticeContent.setActionParams(JSONObject.toJSONString(actionParamsMap));
                taskNoticeContent.setQueryParams(JSONObject.toJSONString(queryParamsMap));

                taskNoticeContent.setCreateBy(loginPersonIdAndName);
                taskNoticeContent.setUpdateBy(loginPersonIdAndName);
                taskNoticeContent.setIsExeRemove(dto.getIsExeRemove());
                super.saveNonNull(taskNoticeContent);
                //写任务接收人信息
                if (CollUtil.isNotEmpty(personInfos)) {
                    //获取不接收任务通知的用户
                    List<TaskNoticeFocus> dislikeTaskNotices = taskNoticeFocusService.getDislikePersonByOperationCode(dto.getOperationCode());
                    List<Long> dislikePersonIds = Lists.newArrayListWithExpectedSize(dislikeTaskNotices.size());
                    if (CollUtil.isNotEmpty(dislikeTaskNotices)) {
                        dislikePersonIds = dislikeTaskNotices.stream().map(TaskNoticeFocus::getPersonId).distinct().collect(Collectors.toList());
                    }
                    List<TaskNoticeDTO> receiverTasks = Lists.newArrayList();
                    List<Long> finalDislikePersonIds = dislikePersonIds;
                    personInfos.stream().forEach(personInfo -> {
                        if (!finalDislikePersonIds.contains(personInfo.getId())) {
                            receiverTasks.add(new TaskNoticeDTO(taskNoticeContent.getOperationCode(), taskNoticeContent.getId(), dto.getSenderId(), dto.getSenderName(), personInfo.getId(), personInfo.getName()));
                        }
                    });
                    taskNoticeService.addBatch(taskNoticeContent, loginVO, receiverTasks);
                }

                //发送钉钉业务通知
                DomainOprationEnum domainOprationEnum = DomainOprationEnum.of(dto.getOperationCode());
                if(Objects.nonNull(domainOprationEnum)
                   && ddRemindOperationCodes.contains(domainOprationEnum.getCode())) {
                    DingTalkNoticeUtil.send2DingDingBiz("",dto.getContent(),ddRemindProperties.getDingding(),profiles);
                }
            } finally {

            }
        });
    }

    @Override
    public TaskNoticeContentVO detail(Long id) {
        TaskNoticeContent taskNoticeContent = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(taskNoticeContent),new ServiceException("任务不存在或已经被执行"));
        return beanMapper.map(taskNoticeContent,TaskNoticeContentVO.class);
    }

    @Override
    public PageInfo<TaskNoticeContentVO> page(TaskNoticeContentQTO qto) {
        //获取当前登录人不想接收到的所有操作码
        List<String> operationCodes = taskNoticeFocusService.getDislikeOperationCodes(SecurityUtil.getCurrentPersonId());
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        qto.setReceiverId(SecurityUtil.getCurrentPersonId());
        //此处查询需要判断当前登录人是否不想接收到某任务通知
        Map<String,Object> params = Maps.newHashMap();
        params.put("qto",qto);
        params.put("operationCodes",operationCodes);
        List<TaskNoticeContentVO> list = taskNoticeContentMapper.list(params);
        return new PageInfo<>(list);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteTaskNotice(String documentType, Serializable documentId, String operationCode) {
        //删除该任务通知下面的接收记录
        List<TaskNoticeContent> taskNoticeContents = taskNoticeContentMapper.selectByExample(Example.builder(TaskNoticeContent.class).where(TsfWeekendSqls.<TaskNoticeContent>custom()
                .andEqualTo(false,TaskNoticeContent::getDocumentType,documentType)
                .andEqualTo(false,TaskNoticeContent::getDocumentId,documentId)
                .andEqualTo(true,TaskNoticeContent::getOperationCode,operationCode)).build());
        if(CollUtil.isNotEmpty(taskNoticeContents)) {
            List<Long> taskNoticeContentIds = taskNoticeContents.stream().map(TaskNoticeContent::getId).collect(Collectors.toList());
            //根据任务查询人员ID
            List<Long> persons = taskNoticeService.findByPersonId(taskNoticeContentIds);
            taskNoticeService.deleteByTaskNoticeIdBatch(taskNoticeContentIds);
            taskNoticeContentMapper.deleteByExample(Example.builder(TaskNoticeContent.class).where(TsfWeekendSqls.<TaskNoticeContent>custom()
                    .andEqualTo(false, TaskNoticeContent::getDocumentType, documentType)
                    .andEqualTo(false, TaskNoticeContent::getDocumentId, documentId)
                    .andEqualTo(false, TaskNoticeContent::getOperationCode, operationCode)).build());
            if(CollUtil.isNotEmpty(persons)){
                //发送消息通知客户端
                WsMessageDTO wsMessageDTO = beanMapper.map(taskNoticeContents.get(0),WsMessageDTO.class);
                wsMessageDTO.setUserIds(persons);
                wsMessageDTO.setContentType(MsgContentTypeEnum.TEXT.getCode());
                wsBiz.send2Client(wsMessageDTO);
            }
        }
    }

    @Override
    public int getMyTaskNoticeNumber(TaskNoticeContentQTO qto) {
        //获取当前登录人不想接收到的所有操作码
        List<String> operationCodes = taskNoticeFocusService.getDislikeOperationCodes(SecurityUtil.getCurrentPersonId());
        qto.setReceiverId(SecurityUtil.getCurrentPersonId());
        Map<String,Object> params = Maps.newHashMap();
        params.put("qto",qto);
        params.put("operationCodes",operationCodes);
        return taskNoticeContentMapper.count(params);
    }
}
